//
// Created by linyongzhi on 2023/12/11.
//

#include <cstdint>
#include <thread>
#include "CPHOpusDecoder.h"
#include "CPHBufferQueue.h"

int CPHOpusDecoder::Init() {
    int err = 0;
    decoder = opus_decoder_create(48000, 2, &err);
    if (err < 0) {
        return -1;
    }

    fpInput = fopen("test.opus", "rb+");
    if (fpInput == NULL) {
        opus_decoder_destroy(decoder);
        return -1;
    }

    decodeThread = new (std::nothrow) std::thread(CPHOpusDecoder::decodeTaskEntry, this);
    if (decodeThread == nullptr) {
        return -1;
    }
    return 0;
}

int CPHOpusDecoder::DeInit() {
    fclose(fpInput);
    opus_decoder_destroy(decoder);
    return 0;
}

int CPHOpusDecoder::Decode() {
    const int inputBuffSize = 240;
    uint8_t inputBuffer[inputBuffSize] = {0};
    const int outputBufferSize = 4096;
    uint8_t outputBuffer[outputBufferSize] = {0};

    while(fread(inputBuffer, inputBuffSize, 1, fpInput) > 0) {
        int pcmLen = opus_decode(decoder, inputBuffer, inputBuffSize, reinterpret_cast<opus_int16 *>(outputBuffer), outputBufferSize, 0);
        if (pcmLen > 0) {
            CPHBuffer pcmData;
            pcmData.Init(4096);
            pcmData.FillInData(outputBuffer, pcmLen * 4);
            pcmBufferQueue->pushData(pcmData);
        }
        std::this_thread::sleep_for(std::chrono::milliseconds(1));
    }
    return 0;
}

void CPHOpusDecoder::decodeTaskEntry(CPHOpusDecoder *opusDecoder) {
    opusDecoder->Decode();
}

void CPHOpusDecoder::SetPCMQueue(CPHBufferQueue *pcmQueue) {
    pcmBufferQueue = pcmQueue;
}